#coding: utf-8
from decimal import Decimal
from django.db import models
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.contrib.auth.signals import user_logged_out
from smart_selects.db_fields import ChainedForeignKey


# Modifica o campo 'username' (que não era utilizado) para armazenar o CPF.
# Evitando assim uma nova tabela para armazenar o CPF.
User._meta.get_field('username').verbose_name = u'CPF'


@receiver(user_logged_out, sender=User)
def apagar_pedidos_em_aberto(sender, request, user, **kwargs):
    user.pedido_set.filter(status=Pedido.EM_ABERTO).delete()


class Telefone(models.Model):
    usuario = models.ForeignKey(User, verbose_name=u'Cliente')
    numero = models.CharField(verbose_name=u'Número', max_length=14)
    
    def __unicode__(self):
        return self.numero


class Bairro(models.Model):
    nome = models.CharField(max_length=30)
    frete = models.DecimalField(max_digits=5, decimal_places=2)
    
    def __unicode__(self):
        return self.nome


class Endereco(models.Model):
    usuario = models.ForeignKey(User, verbose_name=u'Cliente')
    logradouro = models.CharField(max_length=60)
    numero = models.CharField(verbose_name=u'Número', max_length=10)
    complemento = models.CharField(max_length=20, blank=True, null=True)
    bairro = models.ForeignKey(Bairro)
    ponto_ref = models.CharField(verbose_name=u'Ponto de referência', 
        max_length=100, blank=True, null=True)
    
    def __unicode__(self):
        endereco = '%s, %s' % (self.logradouro, self.numero)
        if self.complemento:
            endereco += ', %s' % self.complemento
        endereco += ' - %s' % self.bairro
        #if self.ponto_ref:
        #    endereco += ' (PR: %s)' % self.ponto_ref
        return endereco


class Pedido(models.Model):
    STATUS_CHOICES = (
        ('A', 'Em aberto'),
        ('P', 'Em preparação'),
        ('T', 'Em trânsito'),
        ('E', 'Entregue'),
        ('C', 'Cancelado'),
    )
    
    EM_ABERTO = 'A'
    EM_PREPARACAO = 'P'

    usuario = models.ForeignKey(User, verbose_name=u'Cliente')
    endereco = ChainedForeignKey(Endereco, chained_field='usuario', 
        chained_model_field='usuario', blank=True, null=True)
    telefone = ChainedForeignKey(Telefone, chained_field='usuario', 
        chained_model_field='usuario', blank=True, null=True)
    data = models.DateTimeField(auto_now_add=True)
    status = models.CharField(max_length=1, choices=STATUS_CHOICES)
    valor_pago = models.DecimalField(max_digits=5, decimal_places=2, 
        blank=True, null=True)
    
    def status_printable(self):
        return dict(self.STATUS_CHOICES)[self.status]
    
    def valor_total(self, endereco=None):
        valor = reduce(lambda a,b: a+b, 
            [p.preco_total() for p in self.pizzapedida_set.all()] +
            [i.preco_total() for i in self.itempedido_set.all()] + [Decimal(0)])
        
        if self.endereco and self.status is not self.EM_ABERTO:
            valor += Decimal(self.endereco.bairro.frete)
        elif endereco:
            valor += endereco.bairro.frete
        
        return valor
            
    def troco(self):
        if self.valor_pago:
            return self.valor_pago - self.valor_total()
        else:
            return Decimal(0)
    
    def __unicode__(self):
        return u'%s - Pedido %d [CPF %s]' % (self.status, self.id, 
            self.usuario.username)


class Pizza(models.Model):
    nome = models.CharField(verbose_name=u'Sabor', max_length=30, unique=True)
    descricao = models.CharField(verbose_name=u'Descrição', max_length=60, blank=True, null=True)
    preco_p = models.DecimalField(verbose_name=u'Preço tamanho pequeno', max_digits=5, decimal_places=2)
    preco_m = models.DecimalField(verbose_name=u'Preço tamanho médio', max_digits=5, decimal_places=2)
    preco_g = models.DecimalField(verbose_name=u'Preço tamanho grande', max_digits=5, decimal_places=2)
    
    def __unicode__(self):
        return self.nome


class PizzaPedida(models.Model):
    TAMANHO_CHOICES = (
        ('P', u'Pequena'),
        ('M', u'Média'),
        ('G', u'Grande'),
    )
    
    pedido = models.ForeignKey(Pedido)
    tamanho = models.CharField(max_length=1, choices=TAMANHO_CHOICES)
    pizza = models.ManyToManyField(Pizza)
    quantidade = models.IntegerField()
    
    def preco(self):
        pf = 'preco_%s' % self.tamanho.lower()
        return max([getattr(p, pf) for p in self.pizza.all()])
        
    def preco_total(self):
        return self.preco() * self.quantidade
    
    def __unicode__(self):
        nome = ', '.join([p.nome for p in self.pizza.all()])
        tamanho = dict(self.TAMANHO_CHOICES)[self.tamanho].lower()
        return u'%d Pizza(s) %s(s) de %s' % (self.quantidade, tamanho, nome)


class Categoria(models.Model):
    nome = models.CharField(verbose_name=u'Categoria', max_length=30, 
        unique=True)
    
    def __unicode__(self):
        return self.nome


class Item(models.Model):
    categoria = models.ForeignKey(Categoria)
    nome = models.CharField(verbose_name=u'Item', max_length=30)
    preco = models.DecimalField(verbose_name=u'Preço', max_digits=5, 
        decimal_places=2)
    
    def __unicode__(self):
        return self.nome


class ItemPedido(models.Model):
    pedido = models.ForeignKey(Pedido)
    item = models.ForeignKey(Item)
    quantidade = models.IntegerField()
    
    def preco_total(self):
        return self.quantidade * self.item.preco
    
    def __unicode__(self):
        return u'%s %s(s)' % (self.quantidade, self.item.nome)
